package com.prosay.mvc;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.prosay.mvc.annotation.Controller;
import com.prosay.mvc.annotation.RequestMapping;
import com.prosay.mvc.controller.IndexController;
import com.prosay.mvc.util.ClassScanner;

//@WebServlet(urlPatterns = "*.do", initParams = { @WebInitParam(name = "basePackage", value = "com.prosay.mvc") })
public class DispatcherServlet extends HttpServlet {

	private static final Map<String, Object> controller = new HashMap<String, Object>();
	private static final Map<String, Method> methods = new HashMap<String, Method>();
	// 前缀
	private static String prefix = "/pages";
	// 后缀
	private static String suffix = ".jsp";
	// 分隔符
	private static final String separate = "/";
	//设置编码默认utf-8
	private static String characterEncoding = "utf-8";

	/**
	 * Constructor of the object.
	 */
	public DispatcherServlet() {
	}

	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//设置请求与响应编码
		req.setCharacterEncoding(characterEncoding);
		resp.setCharacterEncoding(characterEncoding);
		// 获取请求路径
		String uri = req.getRequestURI();
		System.out.println("本次请求uri：" + uri);
		// 获取上下文路径
		String contextPath = req.getContextPath();
		// 截取映射路径
		String mappingPath = uri.substring(uri.indexOf(contextPath) + contextPath.length(), uri.indexOf(".do"));
		// 获取指定方法
		Method method = methods.get(mappingPath);
		// 获取类名
		if (method != null) {
			BaseController object = (BaseController) controller.get(method.getDeclaringClass().getName());
			try {
				// 执行方法
				object.init(req, resp);
				String invoke = (String) method.invoke(object);
				req.getRequestDispatcher(this.prefix + this.separate + invoke + this.suffix).forward(req, resp);
			} catch (IllegalAccessException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IllegalArgumentException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (InvocationTargetException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}else{
			
			resp.getWriter().write("你的请求有误，请稍后再试");
		}

	}

	/**
	 * Destruction of the servlet. <br>
	 */
	public void destroy() {
		super.destroy(); // Just puts "destroy" string in log
	}

	/**
	 * Initialization of the servlet. <br>
	 *
	 * @throws ServletException
	 *             if an error occurs
	 */
	public void init() throws ServletException {
		// Put your code here
		ServletConfig config = this.getServletConfig();
		String initParameter = config.getInitParameter("basePackage");
		String prefix = config.getInitParameter("prefix");
		// 不是空就设置前缀
		if (!(prefix == null || "".equals(prefix))) {
			this.prefix = prefix;
		}
		String suffix = config.getInitParameter("suffix");
		// 不是空就设置后缀
		if (!(suffix == null || "".equals(suffix))) {
			this.suffix = suffix;
		}
		String characterEncoding = config.getInitParameter("characterEncoding");
		// 不是空就设置后缀
		if (!(characterEncoding == null || "".equals(characterEncoding))) {
			this.characterEncoding = characterEncoding;
		}
		System.out.println("扫描根目录:" + initParameter);
		Map<String, Class<?>> scannerClass = ClassScanner.scannerClass(initParameter);
		Iterator<String> iterator = scannerClass.keySet().iterator();
		while (iterator.hasNext()) {
			String className = iterator.next();
			Class clazz = IndexController.class;
			boolean annotation = clazz.isAnnotationPresent(Controller.class);
			// 判断这个类是否存在controller注解，是否被标识为controller
			if (annotation) {
				// 管理起来
				System.out.println(clazz.getName() + "被标记为控制器！！");

				String path = "";
				// 判断这个类是否存在RequestMapping注解
				if (clazz.isAnnotationPresent(RequestMapping.class)) {
					RequestMapping anno = (RequestMapping) clazz.getAnnotation(RequestMapping.class);
					path = anno.value();
				}
				try {
					controller.put(className, clazz.newInstance());
				} catch (InstantiationException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				// 拿到这个类的所有公开方法来进行遍历
				Method[] methods = clazz.getMethods();
				for (Method ms : methods) {
					// 如果不存在RequestMapping则跳过这个循环
					if (!ms.isAnnotationPresent(RequestMapping.class)) {
						continue;
					}
					this.methods.put(path + ms.getAnnotation(RequestMapping.class).value(), ms);
					System.out.println("映射的对外路径：" + path + ms.getAnnotation(RequestMapping.class).value());
				}
			}
		}
	}

}
